package cn.tedu.task;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import static cn.tedu.task.Images.gameover;

/**
 * 游戏整体窗口类
 */
public class World extends JPanel {

    /**
     * The constant WIDTH.
     */
    public static final int WIDTH = 641;

    /**
     * The constant HEIGHT.
     */
    public static final int HEIGHT = 479;
    /**
     * 游戏状态：运行状态
     */
    public static final int RUNNING = 0;
    /**
     * 游戏状态：暂停状态
     */
    public static final int PAUSE = 1;
    /**
     * 游戏状态：游戏结束状态
     */
    public static final int GAME_OVER = 2;
    private int state = RUNNING; //当前状态(默认为运行状态)

    private Battleship ship = new Battleship();
    private SeaObject[] submarines = {};
    private Mine[] mines = {};
    private Bomb[] bombs = {};

    /**
     * 生成潜艇对象
     */
    private SeaObject nextSubmarine() {
        Random rand = new Random();
        int type = rand.nextInt(20);
        if (type < 10) {
            return new ObserveSubmarine();
        } else if (type < 16) {
            return new TorpedoSubmarine();
        } else {
            return new MineSubmarine();
        }
    }

    /**
     * 潜艇进场
     */
    private int subEnterIndex = 0;

    private void submarineEnterAction() {
        subEnterIndex++;
        if (subEnterIndex % 40 == 0) {
            SeaObject obj = nextSubmarine();//用变量obj接收生成的潜艇对象
            submarines = Arrays.copyOf(submarines, submarines.length + 1);//扩容
            submarines[submarines.length - 1] = obj;//将obj放入数组最后一位
        }
    }

    /**
     * 水雷进场
     */
    private int mineEnterIndex = 0;

    private void mineEnterAction() {
        mineEnterIndex++;
        if (mineEnterIndex % 100 == 0) {
            for (int i = 0; i < submarines.length; i++) {
                if (submarines[i] instanceof MineSubmarine) {//判断潜艇数组生成的对象是否是水雷潜艇
                    Mine obj = ((MineSubmarine) submarines[i]).shootMine();//潜艇数组强转得到水雷潜艇调用射击水雷方法，用obj接收
                    mines = Arrays.copyOf(mines, mines.length + 1);//扩容
                    mines[mines.length - 1] = obj;//将obj放入数组最后一位
                }

            }

        }
    }
    /**
     * 敌人鱼雷和水雷碰撞战舰
     */
    private void mineBangAction(){
        for (int i = 0; i < mines.length; i++) {
            Mine m = mines[i];
            if (m.isLive() && ship.isLive() && m.isHit(ship)) {
                m.goDead();
                ship.subtractLife(1);//战舰减命1
            }
        }

    }

    /**
     * 碰撞方法
     * 遍历所有炸弹获取炸弹，遍历所有潜艇获取潜艇，判断若都活着并且还撞上了：
     *
     * 炸弹去死、潜艇去死
     *  得东西：
     *   -判断若是分，则强转为分的接口，玩家得分
     *   -判断若是命，则强转为命的接口，获取命数，战舰得命
     */
    private int score = 0;

    private void bombBangAction() {
        for (int i = 0; i < bombs.length; i++) {
            Bomb b = bombs[i];
            for (int j = 0; j < submarines.length; j++) {
                SeaObject s = submarines[j];
                if (b.isLive() && s.isLive() && s.isHit(b)) {
                    s.goDead();
                    b.goDead();

                    if (s instanceof EnemyScore) {
                        EnemyScore es = ((EnemyScore) s);
                        score += es.getScore();
                    }
                    if (s instanceof EnemyLife) {
                        EnemyLife el = ((EnemyLife) s);
                        int num = el.getLife();
                        ship.addLife(num);
                    }

                }
            }
        }
    }

    /**
     * 对象移动
     */
    private void moveAction() {
        for (int i = 0; i < submarines.length; i++) {
            submarines[i].move();
        }
        for (int i = 0; i < mines.length; i++) {
            mines[i].move();
        }
        for (int i = 0; i < bombs.length; i++) {
            bombs[i].move();
        }
    }

    /**
     * 检测游戏结束
     * 判断若战舰的命数<=0，表示游戏结束了
     */
    private void checkGameOverAction() {
        if (ship.getLife() <= 0) {
            state = GAME_OVER;
        }
    }
    private void action() {
        KeyAdapter k = new KeyAdapter() { //不要求掌握
            /** 重写keyReleased()按键抬起事件 */ //keyPressed()按下事件
            @Override
            public void keyReleased(KeyEvent e) { //不要求掌握--当按键抬起时会自动触发
                if(e.getKeyCode()==KeyEvent.VK_P){ //不要求掌握--若抬起的是P键
                    if(state==RUNNING){ //运行状态时修改为暂停状态
                        state = PAUSE;
                    }else if(state==PAUSE){ //暂停状态时修改为运行状态
                        state = RUNNING;
                    }
                }

                if(state==RUNNING){ //仅在运行状态时执行
                    if(e.getKeyCode()== KeyEvent.VK_SPACE){ //不要求掌握---若抬起的是空格键
                        Bomb obj = ship.shootBomb(); //获取炸弹对象
                        bombs = Arrays.copyOf(bombs,bombs.length+1); //扩容
                        bombs[bombs.length-1] = obj; //将obj添加到最后一个元素上
                    }
                    if(e.getKeyCode()==KeyEvent.VK_LEFT){ //不要求掌握--若抬起的是左箭头
                        ship.moveLeft(); //战舰左移
                    }
                    if(e.getKeyCode()==KeyEvent.VK_RIGHT){ //不要求掌握--若抬起的是右箭头
                        ship.moveRight(); //战舰右移
                    }
                }
            }
        };
        this.addKeyListener(k); //不要求掌握

        Timer timer = new Timer();//定时器对象
        int interval = 10;//定时间隔（以毫秒为单位）
        timer.schedule(new TimerTask() {
            @Override
            public void run() {//定时需要运行的事（每10毫秒自动执行）
                if (state == RUNNING) {
                    submarineEnterAction(); //潜艇入场
                    mineEnterAction();      //水雷入场
                    moveAction();           //海洋对象移动
                    outOfBoundsAction();    //删除越界的海洋对象
                    bombBangAction();       //炸弹与潜艇的碰撞
                    mineBangAction();       //水雷与战舰的碰撞
                    checkGameOverAction();  //检测游戏结束
                    repaint(); //重画----系统自动调用paint()方法
                }
            }
        }, interval, interval);//第一个interval指执行到第一次发生的间隔，第二个interval指往后每次间隔
    }

    /**
     * 删除越界对象
     * 遍历所有潜艇/水雷/炸弹，判断若越界了，则：将越界元素替换为最后一个元素，缩容
     */
    private void outOfBoundsAction(){ //每10毫秒走一次
        for(int i=0;i<submarines.length;i++){
            //遍历所有潜艇
            if(submarines[i].isOutOfBounds() || submarines[i].isDead()){ //若越界了或死了的
                submarines[i] = submarines[submarines.length-1]; //将越界元素替换为最后一个元素
                submarines = Arrays.copyOf(submarines,submarines.length-1); //缩容
            }
        }
        for(int i=0;i<mines.length;i++){
            //遍历所有水雷
            if(mines[i].isOutOfBounds() || mines[i].isDead()){ //若越界了或死了的
                mines[i] = mines[mines.length-1]; //将越界元素替换为最后一个元素
                mines = Arrays.copyOf(mines,mines.length-1); //缩容
            }
        }
        for(int i=0;i<bombs.length;i++){
            //遍历所有炸弹
            if(bombs[i].isOutOfBounds() || bombs[i].isDead()){ //若越界了或死了的
                bombs[i] = bombs[bombs.length-1]; //将越界元素替换为最后一个元素
                bombs = Arrays.copyOf(bombs,bombs.length-1); //缩容
            }
        }
    }

    /**
     * 重写来自超类JPanel的方法，用于画图
     */
    public void paint(Graphics g) {
        Images.sea.paintIcon(null, g, 0, 0);//画海洋图
        ship.paintImage(g);
        for (int i = 0; i < submarines.length; i++) {
            submarines[i].paintImage(g);
        }
        for (int i = 0; i < mines.length; i++) {
            mines[i].paintImage(g);
        }
        for (int i = 0; i < bombs.length; i++) {
            bombs[i].paintImage(g);
        }
        g.drawString("分数:" + score, 200, 50);
        g.drawString("命数:" + ship.getLife(), 400, 50);
        if (state == GAME_OVER) {
            gameover.paintIcon(null, g, 0, 0);

        }
    }

    /**
     * The entry point of application.
     *
     * @param args the input arguments
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        world.setFocusable(true);
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH, HEIGHT);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);

        world.action();
    }
}
























